import { ControlVOBase } from '@/core/modules';
import {
	DECtrlActionType,
	IActionResult,
	IContext,
	ICtrlDataAction,
	ICtrlService,
	IDECtrlAbility,
	IDECtrlController,
	IDECtrlControllerParams,
	IDECtrlModel,
	IDECtrlStore,
	IHttpResponse,
	IOpenViewResult,
	IParam,
	IUIService,
} from '../../interface';
import { CtrlController } from './ctrl-controller';

/**
 * 实体部件控制器
 *
 * @export
 * @class DECtrlController
 * @extends {CtrlController<T, S, A>}
 * @implements {IDECtrlController}
 * @template T
 * @template S
 * @template A
 */
export class DECtrlController<
		T,
		S extends IDECtrlStore,
		A extends IDECtrlAbility
	>
	extends CtrlController<T | DECtrlActionType, S, A>
	implements IDECtrlController<S, A>
{
	/**
	 * 部件节点ID
	 *
	 * @protected
	 * @type {string}
	 * @memberof DECtrlController
	 */
	protected controlID!: string;

	/**
	 * 实体部件模型
	 *
	 * @protected
	 * @type {IDECtrlModel}
	 * @memberof DECtrlController
	 */
	protected declare model: IDECtrlModel;

	/**
	 * 部件服务
	 *
	 * @type {*}
	 * @memberof CtrlController
	 */
	ctrlService!: ICtrlService<ControlVOBase>;

	/**
	 * 行为集合
	 *
	 * @protected
	 * @type {IParam}
	 * @memberof DECtrlController
	 */
	protected actions: ICtrlDataAction = {};

	/**
	 * 打开视图
	 *
	 * @protected
	 * @type {(Function | undefined)}
	 * @memberof DECtrlController
	 */
	protected openView: Function | undefined;

	/**
	 * 新建视图
	 *
	 * @protected
	 * @type {(Function | undefined)}
	 * @memberof DECtrlController
	 */
	protected newView: Function | undefined;

	/**
	 * 界面行为服务
	 *
	 * @protected
	 * @type {IUIService}
	 * @memberof DECtrlController
	 */
	protected uiService?: IUIService;

	/**
	 * 是否加载完成
	 *
	 * @type {boolean}
	 * @memberof DECtrlController
	 */
	protected isLoaded: boolean = false;

	/**
	 * Creates an instance of DECtrlController.
	 * @param {IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>} params
	 * @memberof DECtrlController
	 */
	public constructor(
		params: IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>
	) {
		super(params);
	}

	/**
	 * 处理部件初始化
	 *
	 * @protected
	 * @param {(IDECtrlControllerParams<T | DECtrlActionType, A>)} params
	 * @memberof DECtrlController
	 */
	protected processCtrlInit(
		params: IDECtrlControllerParams<T | DECtrlActionType, A>
	): void {
		super.processCtrlInit(params);
		Object.assign(this.store, {
			isLoaded: this.isLoaded,
		});
	}

	/**
	 * 部件初始化前（准备必要参数）
	 *
	 * @protected
	 * @param {IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>} params
	 * @memberof ChartController
	 */
	protected beforeCtrlInit(
		params: IDECtrlControllerParams<DECtrlActionType, IDECtrlAbility>
	) {
		super.beforeCtrlInit(params);
		this.openView = params.openView;
		this.newView = params.newView;
		if (params.actions) {
			this.actions = params.actions;
		}
		this.controlID = params.controlID;
		if (params.ctrlService) {
			this.ctrlService = params.ctrlService;
		}
		this.initUIService();
	}

	/**
	 * 初始化UI服务
	 *
	 * @private
	 * @memberof DECtrlController
	 */
	private initUIService() {
		if (this.model && this.model.entityCodeName) {
			App.getUIService(this.model.entityCodeName)
				.then((service: IUIService) => {
					this.uiService = service;
				})
				.catch((error: any) => {});
		}
	}

	/**
	 * 打开视图
	 *
	 * @return {*}  {void}
	 * @memberof DECtrlController
	 */
	public openData(
		context: IContext,
		viewParams: IParam,
		data: IParam[]
	): Promise<IOpenViewResult> | void {
		if (this.openView) {
			return this.openView(context, viewParams, data);
		}
	}

	/**
	 * 新建视图
	 *
	 * @return {*}  {void}
	 * @memberof DECtrlController
	 */
	public newData(
		context: IContext,
		viewParams: IParam,
		data: IParam[]
	): Promise<IOpenViewResult> | void {
		if (this.newView) {
			return this.newView(context, viewParams, data);
		}
	}

	/**
	 * 异步行为之前
	 *
	 * @param {string} action 行为标识（create/update/load/loadDraft/remove/save/wfStart/wfSubmit/import/search/reset）
	 * @param {IContext} context 应用上下文
	 * @param {IParam} params 视图参数
	 * @param {boolean} [loadding=true]
	 * @return {*}  {Promise<IActionResult>}
	 * @memberof DECtrlController
	 */
	public async beforeAsyncAction(
		action: string,
		context: IContext,
		params: IParam,
		loadding: boolean = true
	): Promise<IActionResult> {
		const { loadingHelper } = this.store;
		if (this.UIEngineContainer) {
			const _action = 'onbefore' + action.toLowerCase();
			const inputParam = this.getUIEngineInputParam({ data: params });
			const res = await this.UIEngineContainer.executeCtrlEvent(
				_action,
				inputParam
			);
			if (res.ok && loadding) {
				// 界面逻辑执行成功开启加载
				loadingHelper.beginLoading(this.controlID);
			}
			await this.onBeforeAction(action, context, params);
			return res;
		} else {
			loadding && loadingHelper.beginLoading(this.controlID);
			await this.onBeforeAction(action, context, params);
			return { ok: true, data: [params] };
		}
	}

	/**
	 * 执行行为之前(用于具体部件重写)
	 *
	 * @param {string} action 行为标识
	 * @param {IContext} context 应用上下文
	 * @param {IParam} params 视图参数
	 * @memberof DECtrlController
	 */
	public async onBeforeAction(
		action: string,
		context: IContext,
		params: IParam
	): Promise<void> {}

	/**
	 * 异步行为之后
	 *
	 * @protected
	 * @param {string} action 行为标识（create/update/load/loadDraft/remove/save/wfStart/wfSubmit/import/search/reset）
	 * @param {IHttpResponse} response 响应结果
	 * @return {*}  {Promise<IActionResult>}
	 * @memberof DECtrlController
	 */
	public async afterAsyncAction(
		action: string,
		response: IHttpResponse
	): Promise<IActionResult> {
		const { loadingHelper } = this.store;
		if (action === 'load') {
			this.store.isLoaded = true;
		}
		loadingHelper.endLoading();
		if (response && response.success === false) {
			App.getNotificationHelper().error(
				App.ts('common.generic.error'),
				response.message || ''
			);
		}
		if (this.UIEngineContainer) {
			const _action =
				'on' + action.toLowerCase() + (response.success ? 'success' : 'error');
			const inputParam = this.getUIEngineInputParam({ data: response.data });
			await this.onAfterAction(action, response);
			return await this.UIEngineContainer.executeCtrlEvent(_action, inputParam);
		} else {
			await this.onAfterAction(action, response);
			return { ok: true, data: [response] };
		}
	}

	/**
	 * 执行行为之后(用于具体部件重写)
	 *
	 * @param {string} action 行为标识
	 * @param {IHttpResponse} response 响应结果
	 * @memberof DECtrlController
	 */
	public async onAfterAction(
		action: string,
		response: IHttpResponse
	): Promise<void> {}

	/**
	 * 获取部件能力
	 *
	 * @return {*}  {A}
	 * @memberof MDCtrlController
	 */
	public getAbility(): A {
		return {
			...super.getAbility(),
			isLoaded: this.isLoaded,
			openData: this.openData.bind(this),
			newData: this.newData.bind(this),
			getData: this.getData.bind(this),
		};
	}

	/**
	 * 获取部件服务
	 *
	 * @return {*}  {ICtrlService<ControlVOBase>}
	 * @memberof DECtrlController
	 */
	public getCtrlService(): ICtrlService<ControlVOBase> {
		return this.ctrlService;
	}
}
